package com.aat.restful.springresteasy.app;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.security.Principal;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;

import org.jboss.resteasy.core.ResourceMethodInvoker;
import org.jboss.resteasy.core.interception.PostMatchContainerRequestContext;
import org.jboss.resteasy.plugins.server.embedded.SimplePrincipal;
import org.jboss.resteasy.plugins.server.netty.NettySecurityContext;
import org.jboss.resteasy.spi.HttpRequest;
import org.springframework.util.StringUtils;

import io.netty.channel.ChannelHandlerContext;

//@Component
//@Provider
public class AppRequestFilter implements ContainerRequestFilter {

	public static final String HEADER_RESTEASY_CLIENT_IP = "X-Resteasy-Client-Ip";
	
	private BodyPostMatchContainerRequestContext body;

	@Override
	public void filter(ContainerRequestContext requestContext) throws IOException {
		PostMatchContainerRequestContext ctx = (PostMatchContainerRequestContext) requestContext;
		getClientIP(ctx);
		authenticate(ctx);
		if ("POST".equals(ctx.getMethod())){
			requestContext.setEntityStream(new ByteArrayInputStream(body.getBody()));
		}

	}

	protected void authenticate(PostMatchContainerRequestContext ctx) throws IOException {
		Principal principal = new SimplePrincipal("Sample" + System.currentTimeMillis());
		ctx.setSecurityContext(new NettySecurityContext(principal, null, "BASIC", true));
		String method = ctx.getMethod();
		//String action = ctx.getUriInfo().getPath();// /test/test
		//String hosts = ctx.getUriInfo().getBaseUri().toString();// http://localhost:56789/
		//System.out.println("method:" + method + "  \nuri:" + ctx.getUriInfo().getRequestUri().toString());
		//System.out.println("action:" +action+" \nhost:"+hosts);
		
		if ("GET".equals(method)) {

		} else {
			HttpRequest request =ctx.getHttpRequest();
			ResourceMethodInvoker resourceMethod = ctx.getResourceMethod();
			body= new BodyPostMatchContainerRequestContext(request,resourceMethod);
			System.out.println("1"+new String(body.getBody()));
		}
	}

	// 获得请求的IP地址
	protected void getClientIP(PostMatchContainerRequestContext requestContext) {
		String ip = null;
		// 互联网访问
		String s1 = requestContext.getHeaderString("X-Real-IP");
		if (s1 == null) {
			// 互联网有代理访问
			s1 = requestContext.getHeaderString("X-Forwarded-For");
			if (s1 == null) {
				// 取socket 层 IP
				ip = getSocketRemoteAddrIp(requestContext);
			} else {
				ip = s1;
			}
		} else {
			ip = s1;
		}
		if (StringUtils.isEmpty(ip)) {
			ip = "0.0.0.0"; // 无法得到ip 时返回 0.0.0.0
		}
		requestContext.getHeaders().putSingle(HEADER_RESTEASY_CLIENT_IP, ip);
	}

	private String getSocketRemoteAddrIp(PostMatchContainerRequestContext requestContext) {
		try {
			Field privateStringField = requestContext.getHttpRequest().getClass().getDeclaredField("ctx");
			privateStringField.setAccessible(true);
			ChannelHandlerContext ctx = (ChannelHandlerContext) privateStringField.get(requestContext.getHttpRequest());
			if (ctx != null && ctx.channel() != null) {
				return ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}
